﻿namespace Lesson_12_结构体
{
    #region 知识点一 基本概念
    //结构体 是一种自定义变量类型 类似枚举需要自己定义
    //它是数据和函数的集合
    //在结构体中 可以申明各种变量和方法

    //作用：用来表现存在关系的数据集合 比如用结构体表现学生 动物 人类等等
    #endregion

    #region 知识点二 基本语法
    //1.结构体一般写在 namespace语句块中
    //2.结构体关键字 struct

    //struct 自定义结构体名
    //{
    //    //第一部分
    //    //变量

    //    //第二部分
    //    //构造函数（可选）

    //    //第三部分
    //    //函数
    //}
    //注意 结构体名字 我们的规范是 帕斯卡命名法
    #endregion

    #region 知识点三 实例
    //表现学生数据的结构体
    //申明结构体 和 申明结构体变量 也是两个概念
    //申明结构体
    struct Student
    {
        #region 知识点五 访问修饰符
        //修饰结构体中变量和方法 是否能被外部使用
        //public 公开 可以被任何地方使用
        //internal 内部 可以被同一个程序集中的其他类使用
        //protected 受保护 可以被同一个程序集中的其他类和派生类使用
        //private 私有 只能被定义在结构体内部使用
        #endregion
        //变量
        //结构体申明的变量 不能直接初始化
        //变量类型 可以写任意类型包括结构体 但是 不能是自己的结构体 可以是其它的
        //Student s; //不能是自己的结构体
        //年龄
        public int age;
        //姓名
        public string name;
        //性别
        char gender;

        //构造函数（可选）
        #region 知识点六 结构体的构造函数
        //基本概念
        //1.没有返回值
        //2.函数名必须和结构体名相同
        //3.必须至少有一个参数
        //4.如果申明了构造函数 那么必须在其中对所有变量进行初始化

        //构造函数 一般是用于在外部方便初始化的
        public Student(int age, bool sex, int number, string name)
        {
            //新的关键字 this 代表当前的结构体实例
            this.age = age;
            this.name = name;
        }

        #endregion

        //函数方法
        //表现这个数据结构的行为

        //注意 在结构体中的方法 目前不需要加static关键字
        public void Speak()
        {
            //函数中可以直接使用结构体内部申明的变量
            Console.WriteLine("我的名字{0},我今年{1}岁",name, age);
        }
    }

    #endregion

    #region 练习题
    struct Monster
    {
        public string name;
        public int atk;

        public Monster(string name)
        {
            this.name = name;
            Random r = new Random();
            atk = r.Next(10, 30);
        }

        public void Atk()
        {
            Console.WriteLine("{0}攻击了我，造成了{1}点伤害", name, atk);
        }
    }

    struct OutMan
    {
        public string name;
        public int atk;
        public int def;
        public int hp;

        public OutMan(string name, int atk, int def, int hp)
        {
            this.name = name;
            this.atk = atk;
            this.def = def;
            this.hp = hp;
        }

        public void Atk(ref Boss monster)
        {
            //奥特曼打boss的逻辑
            monster.hp -= atk - monster.def;
            Console.WriteLine("{0}攻击了{1}，造成了{2}点伤害，{3}剩余{4}点血量", name, monster.name, atk - monster.def, monster.name, monster.hp);
        }
    }

    struct Boss
    {
        public string name;
        public int atk;
        public int def;
        public int hp;

        public Boss(string name, int atk, int def, int hp)
        {
            this.name = name;
            this.atk = atk;
            this.def = def;
            this.hp = hp;
        }

        public void Atk(ref OutMan outman)
        {
            outman.hp -= atk - outman.def;
            Console.WriteLine("{0}攻击了{1}，造成了{2}点伤害，{3}剩余{4}点血量", name, outman.name, atk - outman.def, outman.name, outman.hp);
        }

    }
    
    #endregion
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("结构体");

            #region 知识点四 结构体的使用
            //变量类型 变量名
            Student s1;
            s1.age = 20;
            s1.name = "张三";
            //s1.gender = '男';

            Student s2 = new Student(25, true, 1, "李四");
            s2.Speak();
            #endregion

            Monster[] monsters = new Monster[10];
            for (int i = 0; i < monsters.Length; i++)
            {
                monsters[i] = new Monster("怪物" + i);
            }

            OutMan outMan = new OutMan("路飞", 20, 10, 100);
            Boss boss = new Boss("艾斯", 30, 15, 500);

            while (true)
            {
                outMan.Atk(ref boss);
                if( boss.hp <= 0)
                {
                    Console.WriteLine("艾斯被打败了，{0}胜利", outMan.name);
                    break;
                }
                boss.Atk(ref outMan);
                if(outMan.hp <= 0)
                {
                    Console.WriteLine("路飞被打败了，{0}胜利", boss.name);
                    break;
                }
                Console.WriteLine("按任意键继续");
                Console.ReadKey(true);
            }
        }
    }
    //总结：
    //概念：结构体 struct 是变量和函数的集合 可以用来表现存在关系的数据集合

    //访问修饰符：public 公开 可以被任何地方使用 internal 内部 可以被同一个程序集中的其他类使用 protected 受保护 可以被同一个程序集中的其他类和派生类使用 private 私有 只能被定义在结构体内部使用
    //构造函数：没有返回值 函数名必须和结构体名相同 必须至少有一个参数 如果申明了构造函数 那么必须在其中对所有变量进行初始化 可以重载 主要是帮助我们快速初始化结构体对象

    //注意：
    //1.结构体的变量不能直接初始化 只能在外部或者在函数中进行初始化
    //2.在结构体中申明的函数 不用加static关键字
}
